import { ATeamCombat } from "GameLoop/WorldState/EntityManager/Entitys"
import { EAbsortCode } from "framework/FSM/Action/ActionCode";
import { PositionHelper } from "utils/position/PositionHelper"
import { UtilsHelper } from "utils/position/UtilsHelper";

export class ActionArgHelper
{
    public static warp<T extends IActionCMD,>(action:T,error?:Function,isExpired?:T extends {arg:infer U }?ICompleteVerify<T>:never)
    {
        action.onError = error;
        action.isExpired=isExpired
        return action
    }

    public static isEnemyAttack(action:IActionCMD<keyof ICreepActions>)
    {
        const creep = action.arg.entity
        if(creep.hits<creep.hitsMax)
        {
            creep.pos.lookForInRange(LOOK_CREEPS,4)
        }
    }
    /**
     * action visual
    */
      /**creep boost */
      public static actionVisualHostile(room:Room
        )
        {
            const arg: CreepVisualAction ={
                entity:room,
                 
            }
            return this.actionCMD(arg,"visualHostile")
        }
    //
    public static actionTerminalDeal(room:Room,task:IDealTask,type:"dealbuy"|"dealsell"
        )
    {
        const arg: DealActionArg ={
            entity:room,
            task:task
        }
        return this.actionCMD(arg,type)
    }
    /**creep boost */
    public static actionCreepRenew(creep:Creep,room:Room
    )
    {
        const arg: IRenewCreepActionArg<Creep>={
            entity:creep,
            room:room
        }
        return this.actionCMD(arg,"renewCreep",3,EAbsortCode.BOTH)
    }
    public static actionCreepBoost(creep:Creep,room:Room,boostTask:IBoostTask)
    {
        const arg: IBoostCreepActionArg<Creep>={
            entity:creep,
            room:room,
            boostTask:boostTask
        }
        return this.actionCMD(arg,"boostCreep",3,EAbsortCode.BOTH)
    }
    /*
    lab action
    --------------------------------------------------------------*/
    public static actionLabReaction(room:Room,task:ITask<ILabTaskData<"react">>
)
    {
        const arg: ILabReactionActionArg<Room>={
            entity:room,
            task:task
        }
        return this.actionCMD(arg,"react")
    }
    public static actionClearLab(room:Room,labs:StructureLab[],store:AnyStoreStructure,transportid:string)
    {
        const arg: IClearLabActionArg<Room>={
            entity:room,
            labs:labs,
            store:store,
            transportid:transportid
        }
        return this.actionCMD(arg,"clearLab")
    }
    public static actionClearLabs(room:Room, labs:LabTranportItemArg[],transportid:string)
    {
        const arg: IClearLabActionArg<Room>={
            entity:room,
            labs:labs.map(e=>e.lab),
            store:labs[0].store,
            transportid:transportid
        }
        return this.actionCMD(arg,"clearLab")
    }
    public static actionFillLab(room:Room,   labs:LabTranportItemArg[],transportid:string)
    {
        const arg: IFillLabActionArg<Room>={
            entity:room,
            labs:labs,
          
            transportid:transportid
        }
        return this.actionCMD(arg,"fillLab")
    }
     
    /*creep -----------------------------------------------------------------------*/
    public static actionAccurateTransport(creep:Creep,task:IAccurateTransport  )
    {
        const arg: IAccuateTransportActionArg<Creep>={
            entity:creep,
            task:task
        }
        return this.actionCMD(arg,"accTransport",3,EAbsortCode.BOTH)
    }
    public static actionDefend(creep:Creep,enemy:AttackObject  )
    {
        const arg: IDefendActionArg<Creep>={
            entity:creep,
            enemy:enemy
        }
        return this.actionCMD(arg,"creepdefend",3,EAbsortCode.BOTH)
    }
    public static actionMoveRoom(creep:Creep|PowerCreep, roomName:string)
    {
        const arg: IMoveToActionArg<Creep|PowerCreep>={
            entity:creep,
            goal:{pos:PositionHelper.Create({x:25,y:25,roomName:roomName}),range:21},
            opt:{},
            activerange:21
        }
        // if(creep.pos.distance(PositionHelper.Create({x:25,y:25,roomName:roomName}))>21)
        // {
        //     return false
        // }
        return this.actionCMD(arg,"moveto",1,EAbsortCode.NONE)
    }
    /**
     * 跨中央房星门
     * @param creep 当前爬
     * @param targetRoom 最终要移动到的s目标房间
     * @returns 
     */
    public static actionMoveToPortalRoom(creep:Creep , targetRoom:string)
    {
        const curCenterRoom = PositionHelper.getCenterRoom(creep.room.name);
        if(Game.map.getRoomLinearDistance(curCenterRoom,targetRoom) <=5)
        {
            // 这个中央房已经接近目标房间了
            return false;
        }
        const arg: IMoveToPortalRoomActionArg<Creep >={
            entity:creep,
            room:curCenterRoom
        }
        return this.actionCMD(arg,"movetoPortal",1,EAbsortCode.NONE)
    }
    public static actionMoveto(creep:Creep|PowerCreep,goal:IMoveGoal,opt:IPathFinderOpt,activerange?:number)
    {
        const arg: IMoveToActionArg<Creep|PowerCreep>={
            entity:creep,
            goal:goal,
            opt:opt,
            activerange:activerange
        }
        return this.actionCMD(arg,"moveto",1,EAbsortCode.NONE)
    }
    // 逃跑
    public static actionEscape(creep:Creep|PowerCreep,goal:IMoveGoal[],opt:IPathFinderOpt )
    {
        const arg: IEscapeActionArg<Creep|PowerCreep>={
            entity:creep,
            goals:goal,
        }
        return this.actionCMD(arg,"escape",3,EAbsortCode.BOTH)
    }
    public static actionTeamMoveto(creep:ATeamCombat,goal:IMoveGoal,opt:IPathFinderOpt,key:"lineMove"|"squareMove",activerange?:number)
    {
        const arg:ITeamMoveActionArg<ATeamCombat>={
            entity:creep,
            goal:goal,
            opt:opt,
            activerange:activerange
        }
        return this.actionCMD(arg,key)
    }
    public static actionTeamVisual(creep:ATeamCombat )
    {
        const arg:IBaseActoinArg<ATeamCombat>={
            entity:creep,
            
        }
        return this.actionCMD(arg,"visualTeam")
    }
    public static actionTeamCombatMove(creep:ATeamCombat )
    {
        const arg:ITeamCombatMoveActionArg<ATeamCombat>={
            entity:creep,
          
        }
        return this.actionCMD(arg,"combatMove")
    }
    public static actionAttack(creep:Creep,enemy:AttackObject,type:"attackBlue"|"attackRed")
    {
        const arg: IAttackActionArg<Creep>={
            entity:creep,
            enemy:enemy
        }
        return this.actionCMD(arg,type)
    }
    public static actionHarvest(creep:Creep,source:HarvestObject,time?:number)
    {
        const arg: IHarvestActionArg<Creep>={
            entity:creep,
            source:source,
            time:time
        }
        return this.actionCMD(arg,"harvest",3,EAbsortCode.BOTH)
    }
    public static actionharvestEnergy(creep:Creep,entityId:string)
    {
        const arg: IHarvestEnergyArg<Creep>={
            entity:creep,
            mineEntity:entityId
        }
        return this.actionCMD(arg,"harvestEnergy",3,EAbsortCode.BOTH)
    }
    public static actionBuild(creep:Creep,roomObject:ConstructionSite)
    {
        const arg: IWorkAction<Creep,ConstructionSite>={
            entity:creep,
            roomObject:roomObject
        }
        return this.actionCMD(arg,"build",3,EAbsortCode.BOTH)
    }
    public static actionFill(creep:Creep,workKey:IFVector2)
    {
        const arg: IFillActionArg<Creep >={
            entity:creep,
            workpos:workKey
        }
        return this.actionCMD(arg,"fill")
    }

    public static actionRepair(creep:Creep,roomObject:Structure,targetHit?:number)
    {
        const arg: IRepairAction<Creep>={
            entity:creep,
            roomObject:roomObject,
            goalhit:targetHit
        }
        return this.actionCMD(arg,"repair",3,EAbsortCode.BOTH)
    }
    public static actionUpgrade(creep:Creep,roomObject:StructureController,range=3)
    {
        const arg: IUpgradeActionArg<Creep>={
            entity:creep,
            controller: roomObject,
            range:range
        }
        return this.actionCMD(arg,"upgrade",3,EAbsortCode.BOTH)
    }

    public static actionTransfer(creep:Creep,roomObject:AnyStoreStructure|Creep, transfer?:IResourceItem[] )
    {
        const arg: ITransferActionArg<Creep>={
            entity:creep,
            store:roomObject,
            resource:transfer
        }
        return this.actionCMD(arg,"transfer",3,EAbsortCode.BOTH)
    }
    public static actionWithdraw(creep:Creep,roomObject:AnyStoreStructure|Creep, transfer?:IResourceItem[] )
    {
        const arg: IWithdrawActionArg<Creep>={
            entity:creep,
            store:roomObject,
            resource:transfer
        }
        return this.actionCMD(arg,"withdraw",3,EAbsortCode.BOTH)
    }

    public static actionPickup(creep:Creep,resource:Resource )
    {
        const arg: IPickupActionArg<Creep>={
            entity:creep,
            resource:resource,
            
        }
        return this.actionCMD(arg,"pickup",3,EAbsortCode.BOTH)
    }
    public static actionMoveFill(creep:Creep,targets:Id<AnyStoreStructure>[])
    {
        const arg: IMoveFillArg<Creep>={
            entity:creep,
            targets:targets,
            
        }
        return this.actionCMD(arg,'movefill')
    }
    public static actionDrop(creep:Creep,p:RoomPosition )
    {
        const arg: IDropActionArg<Creep>={
            entity:creep,
            pos:p,
            
        }
        return this.actionCMD(arg,"drop",3,EAbsortCode.BOTH)
    }
    public static actionFoot(creep:Creep  )
    {
        const arg: IBaseActoinArg<Creep>={
            entity:creep,
        }
        return this.actionCMD(arg,"foot",1,EAbsortCode.NONE)
    }
    public static actionController(creep:Creep,controller:StructureController,type:ClaimAction )
    {
        const arg: IControllerActionArg<Creep>={
            entity:creep,
            controller:controller,
            
        }
        return this.actionCMD(arg,type)
    }

    private static actionCMD<T extends ActionKeys>(arg:ActionValue<T>,key:T,priority:number=3,absort:number=0)
    {
        const cmd:IActionCMD<T>=
        {
            arg:arg,
            key:key,
            priority:priority,
            absort:absort,
            ttl:-1,     // 时长 
        }
        return cmd;
    }
}